package wiki.kaizen.cloud.shiro.stateless.shiro;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.springframework.util.StringUtils;
import wiki.kaizen.cloud.shiro.stateless.exception.ErrorTypeEnum;
import wiki.kaizen.cloud.shiro.stateless.properties.SecurityProperties;
import wiki.kaizen.cloud.shiro.stateless.util.JWTUtil;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

/**
 *shiro 无状态 过滤器
 * @author xeepoo
 *  */
public class StatelessAuthFilter extends AccessControlFilter {

    /*
     * 是否允许继续访问 返回结果是false的时候才会执行下面的onAccessDenied方法
     * */
    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
        return false;
    }

    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        // 前段token授权信息放在请求头中传入

        String authorization = httpRequest.getHeader(SecurityProperties.tokenHeaderName);
        if (StringUtils.isEmpty(authorization)) {
            throw ErrorTypeEnum.NOT_LOGIN.getException();
        }
        Claims token;
        try{
            token = JWTUtil.parseJWT(authorization) ;
        }catch (ExpiredJwtException e){
            throw ErrorTypeEnum.EXPIRED_TOKEN.getException();

        } catch (Exception ignore){
            throw ErrorTypeEnum.INVALID_TOKEN.getException();
        }
        String usercode = token.getSubject();
        if (StringUtils.isEmpty(usercode)){
            throw ErrorTypeEnum.INVALID_TOKEN.getException();
        }

        Subject subject = getSubject(request, response);
        /*
         * 委托给Realm进行登录
         * 发生异常 则登录不通过 异常抛出 可通过 全局异常处理捕获
         * */
        subject.login(
            new StatelessToken(usercode,authorization)
        );
        // 通过isPermitted 才能调用doGetAuthorizationInfo方法获取权限信息
        subject.isPermitted(httpRequest.getRequestURI());
        return true;
    }

}
